----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    22:38:31 01/15/2010 
-- Design Name: 
-- Module Name:    Datapath - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- General package
use work.GeneralProperties.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity Datapath is
    Port ( InImediate          : in  STD_LOGIC_VECTOR ((bus_size - 6) downto 0);
	        InMemory            : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
           InExternal          : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
			  OutExternal         : inout STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
			  Flags               : out STD_LOGIC_VECTOR (3 downto 0);
			  SelMuxInput         : in  MultiplexSignals;
           SelAluOp            : in  ALU_operations;
			  SelShifterOp        : in  Shifter_operations;
			  RegFileWriteAddress : in  ProcessorRegisters;
			  RegFileReadAAddress : in  ProcessorRegisters;
			  RegFileReadBAddress : in  ProcessorRegisters;
			  RegFileReadAEnable  : in STD_LOGIC;
			  RegFileReadBEnable  : in STD_LOGIC;
			  WriteRegistersFile  : in STD_LOGIC;
			  RegisterAValue      : out STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
			  RegisterBValue      : out STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
           OutputEnable        : in  STD_LOGIC
			  );
end Datapath;

architecture Behavioral of Datapath is

component Multiplexer
    Port ( 
	        InMemory    : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
			  InExternal  : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
	        InAluOut    : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);	 
           InImediate  : in  STD_LOGIC_VECTOR ((bus_size - 6) downto 0); -- 10 downto 0
           Sel         : in  MultiplexSignals;
           Y           : out  STD_LOGIC_VECTOR ((bus_size - 1) downto 0));
end component;

component ALU
    Port ( A            : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
           B            : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
			  CarryIn      : in std_logic;
           AluSel       : in  ALU_operations;
			  ShifterSel   : in Shifter_operations;
           Output       : out STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
			  FlagCarry    : out std_logic;
			  FlagZero     : out std_logic;
			  FlagSign     : out std_logic;
			  FlagOverflow : out std_logic
			  );
end component;

component RegistersFile
    Port ( 
           InputPort : in  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
           OutPortA : out  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
           OutPortB : out  STD_LOGIC_VECTOR ((bus_size - 1) downto 0);           
           WriteEnable : in  STD_LOGIC;
           WriteAddress : in  ProcessorRegisters;
			  ReadAddPortA : in  ProcessorRegisters;
           ReadAddPortB : in  ProcessorRegisters;
           ReadAEnable : in  STD_LOGIC;
           ReadBEnable : in  STD_LOGIC);
end component;

signal MuxOutput       : STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
signal RFAOutput       : STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
signal RFBOutput       : STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
signal AluOutput       : STD_LOGIC_VECTOR ((bus_size - 1) downto 0);
signal ALUFlagCarry    : STD_LOGIC;
signal ALUFlagZero     : STD_LOGIC;
signal ALUFlagSign     : STD_LOGIC;
signal ALUFlagOverflow : STD_LOGIC;

begin
  -- Multiplexer instance
  Multiplexer0 : Multiplexer port map (InMemory,InExternal,AluOutput,InImediate,SelMuxInput,MuxOutput);
  
  -- Registers File instance
  RegistersFile0 : RegistersFile port map (MuxOutput,RFAOutput,RFBOutput,WriteRegistersFile,RegFileWriteAddress,RegFileReadAAddress,RegFileReadBAddress,RegFileReadAEnable,RegFileReadBEnable);
  RegisterAValue <= RFAOutput;
  RegisterBValue <= RFBOutput;
  
  -- ALU instance
  ALU0 : ALU port map (RFAOutput,RFBOutput,'0',SelAluOp,SelShifterOp,AluOutput,ALUFlagCarry,ALUFlagZero,ALUFlagSign,ALUFlagOverflow);
  Flags <= ALUFlagCarry & ALUFlagZero & ALUFlagSign & ALUFlagOverflow;
  
  -- Tristate buffer
  process (OutputEnable,AluOutput)
  begin 
	if OutputEnable = '1' then
	  OutExternal <= AluOutput;
	else
	  OutExternal <= (others => 'Z');
	end if;
  end process;
  

end Behavioral;

